package com.hevs.samplewebapp.client.screens;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.SimplePager.Resources;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.hevs.samplewebapp.client.bean.CompositeWRefresh;
import com.hevs.samplewebapp.client.bean.MedicalDataItem;
import com.hevs.samplewebapp.client.bean.User;
import com.hevs.samplewebapp.client.screenComponents.ScreenComponentStatistics;
import com.hevs.samplewebapp.client.services.PatientManagementServiceImpl;

/**
 * Widget with the statistics for a patient
 * <p> It gives the doctor the feature of consulting statistics for their patients, for a specific range of date, a type and a category</p> 
 * @author Thomas Rouvinez, Matthias Hurni
 * @Date: 24.04.2012
 */
public class DoctorStatisticsWidget extends CompositeWRefresh{
	// -----------------------------------------------------------------
	// Variables.
	// -----------------------------------------------------------------

	/**
	 * Horizontal panel that contains the widget elements
	 */
	private HorizontalPanel mainPanel=new HorizontalPanel();

	/**
	 * List of medical data of a patient
	 */
	private ListDataProvider<User> patientDataProvider;
	
	/**
	 * List of granted patients
	 */
	private List<User> patients;
	
	/**
	 * Celltable with the list of granted patients in it
	 */
	private CellTable<User> patientsTable;
	
	/**
	 * Column with the patients firstname
	 */
	private TextColumn<User> firstNameColumn;
	
	/**
	 * Column with the patients lastname
	 */
	private TextColumn<User> lastNameColumn;
	
	/**
	 * Handler to sort the patients List by firstname
	 */
	private ListHandler<User> firstNameSortHandler;
	
	/**
	 * Handler to sort the patients List by lastname
	 */
	private ListHandler<User> lastNameSortHandler;
	
	/**
	 * Pager to go trought the list of patient when they are above 15
	 */
	private SimplePager patientsPager;
	
	/**
	 * ClientBundle that provides pager images for this widget   
	 */
	private Resources resources=GWT.create(SimplePager.Resources.class);

	/**
	 * List of medical data for statistics bakery
	 */
	private MedicalDataItem[] medDats;
	
	/**
	 * Graphic component for statistics
	 */
	private ScreenComponentStatistics statistics;

	/**
	 * Currently user selected
	 */
	private User currentEditedPatient;

	/**
	 * Initialization of the Web service for statistics
	 */
	private static PatientManagementServiceImpl patientService = new PatientManagementServiceImpl();
	
	/**
	 * List of patient from the Web service
	 */
	private List<User> patientListRest;
	
	/**
	 * List of medical data from the Web service
	 */
	private List<MedicalDataItem> medDatListRest;

	// -----------------------------------------------------------------
	// Constructor.
	// -----------------------------------------------------------------

	/**
	 * Constructor of the Doctor statistics widget
	 */
	public DoctorStatisticsWidget(){
		mainPanel.setSpacing(8);
		mainPanel.add(patientList());
		
		statistics = new ScreenComponentStatistics();
		statistics.setStatisticsBaked(false);
		mainPanel.add(statistics);

		refreshPatientCellTable();
		initWidget(mainPanel);
	}

	// -----------------------------------------------------------------
	// Methods for patient list and medical data retrieval.
	// -----------------------------------------------------------------

	/**
	 * Method to refresh the patients' cell table. 
	 */
	public void refreshPatientCellTable()
	{
		// Rest call to get a list of patients
		patientsTable.setRowCount(0);
		patientListRest=getPatientList();

		setPatientListListeners();
		patientsTable.setRowCount(patientListRest.size(),true);
		statistics.setStatisticsBaked(false);

		// Reset current user
		currentEditedPatient=null;
	}

	/**
	 * Method to get the patient list from server.
	 * @return
	 * List of granted patients
	 */
	private List<User> getPatientList()
	{
		patientService.getPatients();
		return patientService.getPatientList();
	}

	/**
	 * Method to get the patients' medical data list from server
	 * @return
	 * List of medical data for the selected user
	 */
	private List<MedicalDataItem> getMedDatList()
	{
		patientService.getMedDats(currentEditedPatient.getEmail(), DoctorStatisticsWidget.this);
		return patientService.getMedDatList();
	}

	/**
	 * Method to create the cell table for patients.
	 * @return
	 * The Widget with the celltable in it
	 */
	private Widget patientList()
	{
		VerticalPanel vPanel=new VerticalPanel();
		
		// Initialize local variables.
		patientsTable = new CellTable<User>();
		patientListRest = new ArrayList<User>();
		
		// ------------------------------------------------------------------------
		// Cell table with patients' names
		// ------------------------------------------------------------------------

		// Get the list of patients into the table content provider
		patientDataProvider = new ListDataProvider<User>();
		
		// Create the pager for the table
	    patientsPager=new SimplePager(TextLocation.CENTER,resources,false,1000,true);
	    patientsPager.setDisplay(patientsTable);
	    patientsPager.setPageSize(10);

		// Rest call to get a list of patients
		patientListRest = getPatientList();

		// Create the first name header of column
		firstNameColumn=new TextColumn<User>()
				{
			@Override
			public String getValue(User user)
			{
				return user.getFirstName();
			}
				};

				// Create the last name header of column
				lastNameColumn=new TextColumn<User>()
						{
					@Override
					public String getValue(User user)
					{
						return user.getLastName();
					}
						};

						// Make the relevant columns sortable (all in this case)
						firstNameColumn.setSortable(true);
						lastNameColumn.setSortable(true);

						// Add the columns to the cell table
						patientsTable.addColumn(firstNameColumn,"First name");
						patientsTable.addColumn(lastNameColumn,"Last name");

						// Set columns sizes
						patientsTable.setColumnWidth(firstNameColumn,25.0,Unit.PCT);
						patientsTable.setColumnWidth(lastNameColumn,25.0,Unit.PCT);

						// Add a selection model to handle user selection
						final SingleSelectionModel<User> selectionModel = new SingleSelectionModel<User>();
						patientsTable.setSelectionModel(selectionModel);

						selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
						{
							public void onSelectionChange(SelectionChangeEvent event)
							{
								User selected = selectionModel.getSelectedObject();
								if(selected != null)
								{
									// Set right information in box
									currentEditedPatient = selected;

									// Refresh the list with server sync
									setMedDatListData(0);

									// Prepare for statistics bakery.
									statistics.setStatisticsBaked(false);
								}
							}
						});

						// Set content of the table from the patients in the list
						patientDataProvider.addDataDisplay(patientsTable);
						
						vPanel.add(patientsTable);
						vPanel.add(patientsPager);
						vPanel.setCellHorizontalAlignment(patientsPager,VerticalPanel.ALIGN_CENTER);

						return vPanel;
	}

	/**
	 * Common method to update the cell table completely. 
	 */
	private void setPatientListListeners()
	{
		// Add the patients to the data provider (filling the GUI table)
		patients=patientDataProvider.getList();
		patients.clear();
		for(User patient:patientListRest)
			patients.add(patient);

		// ------------------------------------------------------------------------
		// Cell table's columns sorters
		// ------------------------------------------------------------------------

		// First name sorter listener
		firstNameSortHandler=new ListHandler<User>(patients);
		firstNameSortHandler.setComparator(firstNameColumn,
				new Comparator<User>()
				{
			public int compare(User o1,User o2)
			{
				if(o1==o2)
					return 0;

				// Compare the name columns
				if(o1!=null)
					return (o2!=null)?o1.getFirstName().compareTo(o2.getFirstName()):1;
					return -1;
			}
				});

		// Last name sorter listener
		lastNameSortHandler=new ListHandler<User>(patients);
		lastNameSortHandler.setComparator(lastNameColumn,
				new Comparator<User>()
				{
			public int compare(User o1,User o2)
			{
				if(o1==o2)
					return 0;

				// Compare the name columns
				if(o1!=null)
					return (o2!=null)?o1.getLastName().compareTo(o2.getLastName()):1;
					return -1;
			}
				});

		patientsTable.addColumnSortHandler(firstNameSortHandler);
		patientsTable.addColumnSortHandler(lastNameSortHandler);

		// We know that the data is sorted alphabetically by default
		patientsTable.getColumnSortList().push(firstNameColumn);
		patientsTable.getColumnSortList().push(lastNameColumn);
	}

	/**
	 * Set content of the table from the data into the list.
	 * @param refreshGrade
	 */
	private void setMedDatListData(int refreshGrade)
	{
		switch(refreshGrade)
		{
		// Refresh with server call
		case 0:
			medDatListRest = new ArrayList<MedicalDataItem>();

			// Rest call to get a list of medical data.
			medDatListRest = getMedDatList();

			// Convert medical data list to array for statistics baking.
			medDats = new MedicalDataItem[medDatListRest.size()];

			for(int i = 0 ; i < medDats.length; i++){
				medDats[i] = medDatListRest.get(i);
			}
			
			statistics.setStatisticsBaked(false);
			statistics.setMedicalDataInput(medDats);

			break;

			// Simple table refresh (cause of async server call)
		case 3:
			medDatListRest = new ArrayList<MedicalDataItem>();

			// Get temporary list from Service.
			medDatListRest = patientService.getMedDatList();

			// Convert medical data list to array for statistics baking.
			medDats = new MedicalDataItem[medDatListRest.size()];

			for(int i = 0 ; i < medDats.length; i++){
				medDats[i] = medDatListRest.get(i);
			}
			
			statistics.setStatisticsBaked(false);
			statistics.setMedicalDataInput(medDats);
			
			break;
		default:
			break;
		}
	}

	// ------------------------------------------------------------------------
	// Getters - setters.
	// ------------------------------------------------------------------------
	/**
	 * Getter for the List of medical data
	 * @return
	 * List of medical data
	 */
	public MedicalDataItem[] getMedDats() {
		return medDats;
	}

	@Override
	/**
	 * Method to refresh a component
	 */
	public void refreshComp() {
		// TODO Auto-generated method stub
		
	}
}